
local time = os.time;

local randomseed = math.randomseed;
local random = math.random;

local myseed = nil;

TerrainToy = 
{
	heightmap = Terrain.Heightmap(),
	diamond = Terrain.Diamond(256),
	perlin = Terrain.Perlin(256,256),
	
	terrain_noise_update = false,
	
	terrain_noise = nil,
	diamond_noise = nil,
	
	perlin_weight = 1.0,
	perlin_noise = nil,
	
	diamond_seed = nil,
	perlin_seed = nil,
}

graph:createCanvas("_TerrainGray", 256, 256);

-- 读取图片
function LoadHeightmapFile(path , autoresize)
	autoresize = autoresize or false;
	if not graph:createImageFromPathPlus("_TempImage", path) then
		return;
	end
	
	local iw, ih = graph:getImageSize("_TempImage");
	
	TerrainToy.terrain_noise = Terrain.Noise(512,512);
	graph:createCanvas("_TempCanvas", 513, 513)
	
	graph:setCanvas("_TempCanvas");
	if autoresize then
		local dx, dy = 0, 0;
		local asp = 1.0;
		if iw > ih then
			asp = 512/iw;
			dx = 0;
			dy = (512-asp*ih)/2;
		else
			asp = 512/ih;
			dx = (512-asp*iw)/2;
			dy = 0;
		end
		graph:drawImage("_TempImage", dx, dy, 0, asp, asp);
	else
		graph:drawImage("_TempImage", 0, 0, 0, 512/iw, 512/ih);
	end
	graph:setCanvas();
	
	local idata = graph:getCanvas("_TempCanvas"):getImageData();
	
	for y=0, 512 do
		for x=0, 512 do
			local r,g,b = idata:getPixel(y, x);
			TerrainToy.terrain_noise:setValue((r+g+b)/3/255, x, y);
		end
	end
	
	graph:deleteCanvas("_TempCanvas");
	graph:deleteImage("_TempImage");
	
	TerrainToy.terrain_noise_update = true;
	UpdateTerrain("Terrain");
	UpdateShadow("TerrainShadow");
	return;
end

local function SetRandomseed(seed)
	seed = seed or time();
	randomseed(seed);
end

function CreateGenDiamondCo()
	SetRandomseed(TerrainToy.diamond_seed);
	
	local co = TerrainToy.diamond:CreateCo();
	_, TerrainToy.diamond_noise = coroutine.resume(co);
	return co;
end

function FinishGenDiamond()
	TerrainToy.diamond_noise:normalize();
	if TerrainToy.terrain_noise==nil or 
		TerrainToy.terrain_noise.width~=TerrainToy.diamond_noise.width then
		TerrainToy.terrain_noise = 
			Terrain.Noise(TerrainToy.diamond_noise.width,TerrainToy.diamond_noise.height);
	end
	TerrainToy.terrain_noise:clear();
	TerrainToy.terrain_noise:overlay(TerrainToy.diamond_noise);
	TerrainToy.terrain_noise:normalize();
	TerrainToy.terrain_noise_update = true;
end

function CreateGenPerlinCo(ox, oy, sx, xy)
	SetRandomseed(TerrainToy.perlin_seed);
	TerrainToy.perlin:generateNoise();
	
	local co = TerrainToy.perlin:CreateCo(nil, 
		TerrainToy.diamond.map_dimension, TerrainToy.diamond.map_dimension,
		ox, oy, sx, xy);
	_, TerrainToy.perlin_noise = coroutine.resume(co);
	return co;
end

function FinishGenPerlin()
	TerrainToy.perlin_noise:normalize();
	if TerrainToy.terrain_noise==nil or 
		TerrainToy.terrain_noise.width~=TerrainToy.perlin_noise.width then
		TerrainToy.terrain_noise = 
			Terrain.Noise(TerrainToy.diamond.map_dimension, TerrainToy.diamond.map_dimension);
		TerrainToy.terrain_noise:clear();
	end
	TerrainToy.terrain_noise:overlay(TerrainToy.perlin_noise, TerrainToy.perlin_weight);
	TerrainToy.terrain_noise:normalize();
	TerrainToy.terrain_noise_update = true;
end

function UpdateDiamondGray(cv_idx)
	local noise = TerrainToy.diamond_noise;
	
	if graph:getCanvasSize(cv_idx)~=noise.width then
		graph:deleteCanvas(cv_idx);
		graph:createCanvas(cv_idx, noise.width, noise.height);
	end
	
	-- 更新diamond灰度图
	TerrainToy.heightmap:setNoise(noise);
	TerrainToy.heightmap:DrawHeightMap(graph:getCanvas(cv_idx))
end

function UpdatePerlinGray(cv_idx)
	local noise = TerrainToy.perlin_noise;
	
	if graph:getCanvasSize(cv_idx)~=noise.width then
		graph:deleteCanvas(cv_idx);
		graph:createCanvas(cv_idx, noise.width, noise.height);
	end
	
	-- 更新diamond灰度图
	TerrainToy.heightmap:setNoise(noise);
	TerrainToy.heightmap:DrawHeightMap(graph:getCanvas(cv_idx))
end

function UpdateTerrain(cv_idx)
	local noise = TerrainToy.terrain_noise;
	if noise==nil then
		return;
	end
	
	if graph:getCanvasSize("_TerrainGray")~=noise.width then
		graph:deleteCanvas("_TerrainGray");
		graph:createCanvas("_TerrainGray", noise.width, noise.height);
	end
	
	if graph:getCanvasSize(cv_idx)~=noise.width then
		graph:deleteCanvas(cv_idx);
		graph:createCanvas(cv_idx, noise.width, noise.height);
		
		uitable.terrain_wnd:setSize(noise.width+10, noise.height+24)
		uitable.terrain_wnd:get("bg"):setSize(uitable.terrain_wnd:getSize());
		uitable.terrain_wnd:get("bg")
			:get("terrain_bg"):setSize(noise.width,noise.height);
		uitable.terrain_wnd:get("bg")
			:get("terrain_bg")
			:get("terrain"):setSize(noise.width,noise.height);
		uitable.terrain_wnd:get("bg")
			:get("terrain_bg")
			:get("terrain")
			:get("terrain_sd"):setSize(noise.width,noise.height);
	end
	
	-- 更新diamond灰度图
	if TerrainToy.terrain_noise_update then
		TerrainToy.heightmap:setNoise(noise);
		TerrainToy.heightmap:DrawHeightMap(graph:getCanvas("_TerrainGray"))
		TerrainToy.terrain_noise_update = false;
	end
	
	-- 更新Terrain图
	graph:getCanvas(cv_idx):clear();
	graph._setColor({255,255,255});
	graph:setCanvas(cv_idx);
	TerrainToy.heightmap:DrawTerrain(graph:getCanvas("_TerrainGray"));
	graph:setCanvas();
end

function UpdateShadow(sd_idx)
	local noise = TerrainToy.terrain_noise;
	if noise==nil then
		return;
	end

	if graph:getCanvasSize(sd_idx)~=noise.width then
		graph:deleteCanvas(sd_idx);
		graph:createCanvas(sd_idx, noise.width, noise.height);
	end
	
	graph:getCanvas(sd_idx):clear();
	graph._setColor({0,0,0,220});
	graph:setCanvas(sd_idx);
	TerrainToy.heightmap:DrawShadow(graph:getCanvas("_TerrainGray"));
	graph:setCanvas();
	graph._setColor({255,255,255});
end
